home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / layout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  25.9 KB  |  991 lines

  1. /* Panel layout module for the Midnight Commander
  2.    Copyright (C) 1995 the Free Software Foundation
  3.    
  4.    Written: 1995 Janne Kukonlehto
  5.             1995 Miguel de Icaza
  6.  
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.  
  12.    This program is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with this program; if not, write to the Free Software
  19.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
  20.  */
  21.  
  22. #include <config.h>
  23. #include <stdlib.h>
  24. #include <stdarg.h>
  25. #include <stdio.h>
  26. #include <string.h>
  27. #include <sys/param.h>        /* Required by tree.h */
  28. #include <sys/types.h>
  29. #include <sys/param.h>
  30. #include <sys/stat.h>
  31. #include <termios.h>
  32. #ifdef HAVE_UNISTD_H
  33. #   include <unistd.h>
  34. #endif
  35. #include <signal.h>
  36. #include "tty.h"
  37. #include "mad.h"
  38. #include "util.h"        /* Needed for the externs */
  39. #include "win.h"
  40. #include "color.h"
  41. #include "key.h"
  42.  
  43. #include "dlg.h"
  44. #include "widget.h"
  45. #include "command.h"
  46.  
  47. #include "dialog.h"        /* For do_refresh() */
  48. #include "profile.h"        /* For sync_profiles() */
  49. #include "mouse.h"
  50. #define WANT_WIDGETS
  51. #include "main.h"
  52. #include "subshell.h"    /* For use_subshell and resize_subshell() */
  53. #include "tree.h"
  54. #include "menu.h"
  55.  
  56. /* Needed for the extern declarations of integer parameters */
  57. #include "dir.h"
  58. #include "panel.h"        /* The Panel widget */
  59. #include "file.h"
  60. #include "cons.saver.h"
  61. #include "layout.h"
  62. #include "info.h"        /* The Info widget */
  63. #include "view.h"        /* The view widget */
  64.  
  65. #define WANT_DEFAULTS
  66. #include "setup.h"        /* For save_setup() */
  67.  
  68. #ifdef HAVE_TK
  69. #   include <tcl.h>
  70. #   include <tk.h>
  71. #   include "tkmain.h"
  72. #endif
  73.  
  74. /* "$Id: layout.c,v 1.2 1995/02/21 19:06:17 miguel Exp $" */
  75.  
  76. /* The maximum number of views managed by the set_display_type routine */
  77. /* Must be at least two (for current and other).  Please note that until */
  78. /* Janne gets around this, we will only manage two of them :-) */
  79. #define MAX_VIEWS 2
  80.  
  81. /* If set, then we have to call the layout_change routine from main */
  82. int layout_do_change = 0;
  83.  
  84. /* Controls the display of the rotating dash on the verbose mode */
  85. int nice_rotating_dash = 1;
  86.  
  87. /* Set if the window has changed it's size */
  88. int winch_flag = 0;
  89.  
  90. /* Set if the panels are split horizontally */
  91. int horizontal_split = 0;
  92.  
  93. /* Set if the split is the same */
  94. int equal_split = 1;
  95.  
  96. /* First panel size if the panel are not split equally */
  97. int first_panel_size = 0;
  98.  
  99. /* The number of output lines shown (if available) */
  100. int output_lines = 0;
  101.  
  102. /* Set if the command prompt is to be displayed */
  103. int command_prompt = 1;
  104.  
  105. /* Set if the nice and usefull keybar is visible */
  106. int keybar_visible = 1;
  107.  
  108. /* Set if the nice message (hint) bar is visible */
  109. int message_visible = 1;
  110.  
  111. /* Set if you want the message bar shown in xterm title bar to save space */
  112. int xterm_hintbar = 1;
  113.  
  114. /* The starting line for the output of the subprogram */
  115. int output_start_y = 0;
  116.  
  117. static struct {
  118.     int    type;
  119.     Widget *widget;
  120. } panels [MAX_VIEWS];
  121.  
  122. /* These variables are used to avoid updating the information unless */
  123. /* we need it */
  124. static int old_first_panel_size;
  125. static int old_horizontal_split;
  126. static int old_output_lines;
  127.  
  128. /* Internal variables */
  129. static int _horizontal_split;
  130. static int _equal_split;
  131. static int _first_panel_size;
  132. static int _menubar_visible;
  133. static int _output_lines;
  134. static int _command_prompt;
  135. static int _keybar_visible;
  136. static int _message_visible;
  137. static int _xterm_hintbar;
  138.  
  139. static int height;
  140.  
  141. #define MINWIDTH 10
  142. #define MINHEIGHT 5
  143.  
  144. #define BX      12
  145. #define BY      11
  146.  
  147. #define B_2LEFT B_USER
  148. #define B_2RIGHT B_USER + 1
  149. #define B_PLUS B_USER + 2
  150. #define B_MINUS B_USER + 3
  151.  
  152. static Dlg_head *layout_dlg;
  153.  
  154. static char *s_split_direction [2] = {"Vertical", "Horizontal"};
  155. WRadio *radio_widget;
  156.  
  157. static struct {
  158.     char   *text;
  159.     int    *variable;
  160.     WCheck *widget;
  161.     int    hkey;
  162.     int    hpos;
  163. } check_options [] = {
  164.     { "Xterm hintbar",      &xterm_hintbar,0, 'X', 0 },
  165.     { "hIntbar visible",  &message_visible,0, 'I', 1 },
  166.     { "Keybar visible",   &keybar_visible, 0, 'K', 0 },
  167.     { "command Prompt",   &command_prompt, 0, 'P', 8 },
  168.     { "show Mini status", &show_mini_info, 0, 'M', 5 },
  169.     { "menuBar visible",  &menubar_visible, 0, 'B',4 },
  170.     { "Equal split",      &equal_split, 0, 'E', 0 },
  171.     { 0, 0, 0, 0, 0 }
  172. };
  173.  
  174. static WButton *bleft_widget, *bright_widget;
  175.  
  176. static void _check_split (void)
  177. {
  178.     if (_horizontal_split){
  179.     if (_equal_split)
  180.         _first_panel_size = height / 2;
  181.     else if (_first_panel_size < MINHEIGHT)
  182.         _first_panel_size = MINHEIGHT;
  183.     else if (_first_panel_size > height - MINHEIGHT)
  184.         _first_panel_size = height - MINHEIGHT;
  185.     } else {
  186.     if (_equal_split)
  187.         _first_panel_size = COLS / 2;
  188.     else if (_first_panel_size < MINWIDTH)
  189.         _first_panel_size = MINWIDTH;
  190.     else if (_first_panel_size > COLS - MINWIDTH)
  191.         _first_panel_size = COLS - MINWIDTH;
  192.     }
  193. }
  194.  
  195. static void update_split (void)
  196. {
  197.     /* Check split has to be done before testing if it changed, since
  198.        it can change due to calling _check_split() as well*/
  199.     _check_split ();
  200.     
  201.     /* To avoid setting the cursor to the wrong place */
  202.     if ((old_first_panel_size == _first_panel_size) &&
  203.     (old_horizontal_split == _horizontal_split)){
  204.     return;
  205.     }
  206.  
  207.     old_first_panel_size = _first_panel_size;
  208.     old_horizontal_split = _horizontal_split; 
  209.    
  210.     attrset (REVERSE_COLOR);
  211.     dlg_move (layout_dlg, 6, 11);
  212.     printw ("%03d", _first_panel_size);
  213.     dlg_move (layout_dlg, 6, 20);
  214.     if (_horizontal_split)
  215.     printw ("%03d", height - _first_panel_size);
  216.     else
  217.     printw ("%03d", COLS - _first_panel_size);
  218. }
  219.  
  220. static int b2left_cback (int action, void *data)
  221. {
  222.     if (_equal_split){
  223.     /* Turn equal split off */
  224.     _equal_split = 0;
  225.     check_options [6].widget->state = check_options [6].widget->state & ~C_BOOL;
  226.     dlg_select_widget (layout_dlg, check_options [6].widget);
  227.     dlg_select_widget (layout_dlg, bleft_widget);
  228.     }
  229.     _first_panel_size++;
  230.     return 0;
  231. }
  232.  
  233. static int b2right_cback (int action, void *data)
  234. {
  235.     if (_equal_split){
  236.     /* Turn equal split off */
  237.     _equal_split = 0;
  238.     check_options [6].widget->state = check_options [6].widget->state & ~C_BOOL;
  239.     dlg_select_widget (layout_dlg, check_options [6].widget);
  240.     dlg_select_widget (layout_dlg, bright_widget);
  241.     }
  242.     _first_panel_size--;
  243.     return 0;
  244. }
  245.  
  246. static int bplus_cback (int action, void *data)
  247. {
  248.     _output_lines++;
  249.     return 0;
  250. }
  251.  
  252. static int bminus_cback (int action, void *data)
  253. {
  254.     if (_output_lines > 0)
  255.     _output_lines--;
  256.     return 0;
  257. }
  258.  
  259. static int layout_callback (struct Dlg_head *h, int Id, int Msg)
  260. {
  261.     switch (Msg){
  262.     case DLG_DRAW:
  263.         /*When repainting the whole dialog (e.g. with C-l) we have to
  264.           update everything*/
  265.        old_first_panel_size = -1;
  266.         old_horizontal_split = -1;
  267.         old_output_lines     = -1;
  268.     attrset (REVERSE_COLOR);
  269.     dlg_erase (h);
  270.     draw_box (h, 1, 2, 12, 56);
  271.     draw_box (h, 2, 5, 6, 24);
  272.     draw_box (h, 2, 31, 9, 24);
  273.  
  274.     attrset (COLOR_HOT_NORMAL);
  275.     dlg_move (h, 1, 24);
  276.     addstr (" Layout ");
  277.     dlg_move (h, 2, 6);
  278.     addstr (" Panel split ");
  279.     dlg_move (h, 2, 32);
  280.     addstr (" Other options ");
  281.     update_split ();
  282.     dlg_move (h, 6, 16);
  283.     addstr ("--");
  284.     if (console_flag){
  285.         if (old_output_lines != _output_lines){
  286.         old_output_lines = _output_lines;
  287.         dlg_move (h, 9, 34);
  288.         printw ("%02d", _output_lines);
  289.         dlg_move (h, 9, 38);
  290.         addstr ("lines of output");
  291.         }
  292.     }
  293.     break;
  294.  
  295.     case DLG_POST_KEY:
  296.     _equal_split = check_options [6].widget->state & C_BOOL;
  297.     _menubar_visible = check_options [5].widget->state & C_BOOL;
  298.     _command_prompt = check_options [4].widget->state & C_BOOL;
  299.     _keybar_visible = check_options [2].widget->state & C_BOOL;
  300.     _message_visible = check_options [1].widget->state & C_BOOL;
  301.     _xterm_hintbar = check_options [0].widget->state & C_BOOL;
  302.     if (console_flag){
  303.         int minimum;
  304.         if (_output_lines < 0)
  305.         _output_lines = 0;
  306.         height = LINES - _keybar_visible - _command_prompt -
  307.              _menubar_visible - _output_lines - _message_visible;
  308.         if (_message_visible && _xterm_hintbar && xterm_flag) height++;
  309.         minimum = MINHEIGHT * (1 + _horizontal_split);
  310.         if (height < minimum){
  311.         _output_lines -= minimum - height;
  312.         height = minimum;
  313.         }
  314.     } else {
  315.         height = LINES - _keybar_visible - _command_prompt -
  316.         _menubar_visible - _output_lines - _message_visible;
  317.         if (_message_visible && _xterm_hintbar && xterm_flag) height++;
  318.     }
  319.     if (_horizontal_split != radio_widget->sel){
  320.         _horizontal_split = radio_widget->sel;
  321.         if (_horizontal_split)
  322.         _first_panel_size = height / 2;
  323.         else
  324.         _first_panel_size = COLS / 2;
  325.     }
  326.     update_split ();
  327.     if (console_flag){
  328.         if (old_output_lines != _output_lines){
  329.         old_output_lines = _output_lines;
  330.         dlg_move (h, 9, 34);
  331.         printw ("%02d", _output_lines);
  332.         }
  333.     }
  334.     break;
  335.  
  336.     case DLG_END:
  337.     break;
  338.     }
  339.     return 0;
  340. }
  341.  
  342. static void init_layout (void)
  343. {
  344.     int i;
  345.  
  346.     layout_dlg = create_dlg (0, 0, 14, 60, dialog_colors, layout_callback,
  347.                  "[Layout]", "layout", DLG_CENTER);
  348.                  
  349.     x_set_dialog_title (layout_dlg, "Layout");
  350.  
  351.     add_widgetl (layout_dlg,
  352.         button_new (BY, BX+26, B_CANCEL, "[ Cancel ]",'c',2, 0, 0), 
  353.         XV_WLAY_RIGHTOF);
  354.     add_widgetl (layout_dlg,
  355.         button_new (BY, BX+12, B_EXIT,   "[ Save ]",'s',2, 0, 0),
  356.         XV_WLAY_RIGHTOF);
  357.     add_widgetl (layout_dlg,
  358.         button_new (BY, BX,    B_ENTER,  "[[ Ok ]]",'o',3, 0, 0),
  359.         XV_WLAY_CENTERROW);
  360. #ifndef HAVE_X
  361.     if (console_flag){
  362.     add_widget (layout_dlg,
  363.             button_new (9, 36, B_MINUS, "-", '-', 0, bminus_cback, 0));
  364.     add_widget (layout_dlg,
  365.             button_new (9, 33, B_PLUS, "+", '+', 0, bplus_cback, 0));
  366.     }
  367. #endif    
  368.  
  369. #define XTRACT(i) *check_options[i].variable, check_options[i].text,                             check_options[i].hkey, check_options[i].hpos
  370.  
  371.     for (i = 0; i < 6; i++){
  372.     check_options [i].widget = check_new (8 - i, 33, XTRACT(i));
  373.     add_widgetl (layout_dlg, check_options [i].widget, XV_WLAY_BELOWCLOSE);
  374.     }
  375. #ifdef HAVE_X
  376.     add_widgetl (layout_dlg, label_new (2, 32, " Other options "), 
  377.         XV_WLAY_NEXTCOLUMN);
  378.     add_widgetl (layout_dlg, label_new (2, 6, " Panel split "),
  379.         XV_WLAY_NEXTCOLUMN);
  380. #endif        
  381.     _equal_split = equal_split;
  382.     _menubar_visible = menubar_visible;
  383.     _command_prompt = command_prompt;
  384.     _keybar_visible = keybar_visible;
  385.     _message_visible = message_visible;
  386.     _xterm_hintbar = xterm_hintbar;
  387.     bright_widget = button_new(6, 18, B_2RIGHT, ">", '>', 0, b2right_cback, 0);
  388.     add_widgetl (layout_dlg, bright_widget, XV_WLAY_RIGHTOF);
  389.     bleft_widget = button_new (6, 15, B_2LEFT, "<", '<', 0, b2left_cback, 0);
  390.     add_widgetl (layout_dlg, bleft_widget, XV_WLAY_RIGHTOF);
  391.     check_options [6].widget = check_new (5, 8, XTRACT(6));
  392.  
  393.     old_first_panel_size = -1;
  394.     old_horizontal_split = -1;
  395.     old_output_lines     = -1;
  396.     
  397.     _first_panel_size = first_panel_size;
  398.     _output_lines = output_lines;
  399.     add_widget (layout_dlg, check_options [6].widget);
  400.     radio_widget = radio_new (3, 8, 2, s_split_direction, 1);
  401.     add_widget (layout_dlg, radio_widget);
  402.     radio_widget->sel = horizontal_split;
  403. }
  404.  
  405. void layout_change (void)
  406. {
  407.     setup_panels ();
  408.     layout_do_change = 0;
  409. }
  410.  
  411. void layout_cmd (void)
  412. {
  413.     int result;
  414.     int i;
  415.  
  416.     init_layout ();
  417.     run_dlg (layout_dlg);
  418.     result = layout_dlg->ret_value;
  419.  
  420.     if (result == B_ENTER || result == B_EXIT){
  421.     for (i = 0; check_options [i].text; i++)
  422.         *check_options [i].variable = check_options [i].widget->state & C_BOOL;
  423.     horizontal_split = radio_widget->sel;
  424.     first_panel_size = _first_panel_size;
  425.     output_lines = _output_lines;
  426.  
  427.     layout_do_change = 1;
  428.     }
  429.     if (result == B_EXIT){
  430.     save_layout ();
  431.     sync_profiles ();
  432.     }
  433.  
  434.     destroy_dlg (layout_dlg);
  435.     if (layout_do_change)
  436.     layout_change ();
  437. }
  438.  
  439. static void check_split (void)
  440. {
  441.     if (horizontal_split){
  442.     if (equal_split)
  443.         first_panel_size = height / 2;
  444.     else if (first_panel_size < MINHEIGHT)
  445.         first_panel_size = MINHEIGHT;
  446.     else if (first_panel_size > height - MINHEIGHT)
  447.         first_panel_size = height - MINHEIGHT;
  448.     } else {
  449.     if (equal_split)
  450.         first_panel_size = COLS / 2;
  451.     else if (first_panel_size < MINWIDTH)
  452.         first_panel_size = MINWIDTH;
  453.     else if (first_panel_size > COLS - MINWIDTH)
  454.         first_panel_size = COLS - MINWIDTH;
  455.     }
  456. }
  457.  
  458. int panel_event    (Gpm_Event *event, WPanel *panel);
  459. int menu_bar_event (Gpm_Event *event, void *);
  460. extern char *prompt;
  461.  
  462. #ifdef HAVE_SLANG
  463. void init_curses ()
  464. {
  465.     do_enter_ca_mode ();
  466.     init_colors ();
  467.     keypad (stdscr, TRUE);
  468.     nodelay (stdscr, FALSE);
  469. }
  470. #else
  471. void init_curses (void)
  472. {
  473.     if (!status_using_ncurses)
  474.     do_enter_ca_mode ();
  475.     mc_raw_mode ();
  476.     noecho ();
  477.     keypad (stdscr, TRUE);
  478.     nodelay (stdscr, FALSE);
  479.     init_colors ();
  480. }
  481. #endif
  482.  
  483. void panel_do_cols (int index)
  484. {
  485.     if (get_display_type (index) == view_listing)
  486.     panel_update_format ((WPanel *) panels [index].widget);
  487.     else {
  488.     panel_update_cols (panels [index].widget, frame_half);
  489.     }
  490. }
  491.  
  492. #ifdef HAVE_X
  493. void setup_panels (void)
  494. {
  495.     Widget *w = panels [0].widget;
  496.  
  497.     winput_set_origin (&cmdline->input, 0, 60);
  498.  
  499.     /* Only needed by the startup code */
  500.     if (panels [0].type == view_listing){
  501.     x_panel_set_size (0);
  502.     }
  503.     
  504.     if (panels [1].type == view_listing){
  505.     x_panel_set_size (1);
  506.     }
  507.     
  508. #ifdef HAVE_XVIEW
  509.     panel_do_cols (0);
  510.     panel_do_cols (1);
  511. #endif    
  512. }
  513.  
  514. #else
  515.  
  516. void setup_panels (void)
  517. {
  518.     int start_y;
  519.     int promptl;        /* the prompt len */
  520.  
  521.     if (console_flag){
  522.     int minimum;
  523.     if (output_lines < 0)
  524.         output_lines = 0;
  525.     height = LINES - keybar_visible - command_prompt - menubar_visible
  526.              - output_lines - message_visible;
  527.     if (message_visible && xterm_hintbar && xterm_flag) height++;
  528.     minimum = MINHEIGHT * (1 + horizontal_split);
  529.     if (height < minimum){
  530.         output_lines -= minimum - height;
  531.         height = minimum;
  532.     }
  533.     } else {
  534.     height = LINES - menubar_visible - command_prompt -
  535.         keybar_visible - message_visible;
  536.     if (message_visible && xterm_hintbar && xterm_flag) height++;
  537.     }
  538.     check_split ();
  539.     start_y = menubar_visible;
  540.  
  541.     /* The column computing is defered until panel_do_cols */
  542.     if (horizontal_split){
  543.     widget_set_size (panels [0].widget, start_y, 0, 
  544.              first_panel_size, 0);
  545.             
  546.     widget_set_size (panels [1].widget, start_y+first_panel_size, 0,
  547.              height-first_panel_size, 0);
  548.     } else {
  549.     int first_x = first_panel_size;
  550.  
  551.     widget_set_size (panels [0].widget, start_y, 0,
  552.              height, 0);
  553.  
  554.     widget_set_size (panels [1].widget, start_y, first_x,
  555.              height, 0);
  556.             
  557.     }
  558.     panel_do_cols (0);
  559.     panel_do_cols (1);
  560.     
  561.     promptl = strlen (prompt);
  562.  
  563.     widget_set_size (&the_menubar->widget, 0, 0, 1, COLS);
  564.  
  565.     if (command_prompt) {
  566.         widget_set_size (&cmdline->input.widget,
  567.                  LINES-1-keybar_visible, promptl,
  568.                  1, COLS-promptl);
  569.         winput_set_origin (&cmdline->input, promptl, COLS-promptl);
  570.         widget_set_size (&the_prompt->widget,
  571.                  LINES-1-keybar_visible, 0,
  572.                  1, promptl);
  573.     } else {
  574.         widget_set_size (&cmdline->input.widget, 0, 0, 0, 0);
  575.         winput_set_origin (&cmdline->input, 0, 0);
  576.         widget_set_size (&the_prompt->widget, LINES, COLS, 0, 0);
  577.     }                 
  578.  
  579.     widget_set_size (&the_bar->widget, LINES-1, 0, 1, COLS);
  580.     the_bar->visible = keybar_visible;
  581.     
  582.     /* Output window */
  583.     if (console_flag && output_lines){
  584.     output_start_y = LINES -command_prompt-keybar_visible-
  585.         output_lines;
  586.     show_console_contents (output_start_y,
  587.                    LINES-output_lines-keybar_visible-1,
  588.                    LINES-keybar_visible-1);
  589.     } 
  590.     if (message_visible && (!xterm_hintbar || !xterm_flag))
  591.     widget_set_size (&the_hint->widget, height+start_y, 0, 1,COLS);
  592.     else
  593.     widget_set_size (&the_hint->widget, 0, 0, 0, 0);
  594.     
  595.     load_hint ();
  596. }
  597. #endif
  598.  
  599. void flag_winch (int dummy)
  600. {
  601.     winch_flag = 1;
  602. }
  603.  
  604. void change_screen_size (void)
  605. {
  606. #ifndef HAVE_X
  607. #ifdef HAVE_SLANG
  608. #if defined TIOCGWINSZ && !defined SCO_FLAVOR
  609.     struct winsize winsz;
  610.     extern Dlg_head *view_dlg;
  611.     
  612.     mc_noraw_mode ();
  613.     endwin ();
  614.     winsz.ws_col = winsz.ws_row = 0;
  615.  
  616.     /* Ioctl on the STDIN_FILENO */
  617.     ioctl (0, TIOCGWINSZ, &winsz);
  618.     if (winsz.ws_col && winsz.ws_row){
  619.     COLS = winsz.ws_col;
  620.     LINES = winsz.ws_row;
  621. #ifdef HAVE_SUBSHELL_SUPPORT
  622.         resize_subshell ();
  623. #endif
  624.     }
  625.  
  626.     check_split ();
  627.     initscr ();
  628.     init_curses ();
  629.     setup_panels ();
  630.     if (current_dlg == view_dlg)
  631.     view_adjust_size (view_dlg);
  632.     
  633.     /* Now, force the redraw */
  634.     do_refresh ();
  635.     touchwin (stdscr);
  636. #endif /* TIOCGWINSZ && !SCO_FLAVOR */
  637. #endif /* HAVE_SLANG */
  638. #endif /* HAVE_X */
  639.     winch_flag = 0;
  640. }
  641.  
  642. extern int verbose;
  643. static int ok_to_refresh = 1;
  644.  
  645. void use_dash (int flag)
  646. {
  647.     if (flag)
  648.     ok_to_refresh++;
  649.     else
  650.     ok_to_refresh--;
  651. }
  652.  
  653. void set_hintbar(char *str) 
  654. {
  655. #ifndef HAVE_X
  656.     if (xterm_flag && xterm_hintbar) {
  657.         fprintf (stderr, "\33]0;mc - %s\7", str);
  658.     } else
  659. #endif
  660.     {
  661.         label_set_text (the_hint, str);
  662.         if (ok_to_refresh > 0)
  663.         refresh();
  664.     }
  665. }
  666.  
  667. void print_vfs_message(char *msg, ...)
  668. {
  669.     va_list ap;
  670.     char str[128];
  671.  
  672.     va_start(ap, msg);
  673.     vsprintf(str, msg, ap);
  674.     va_end(ap);
  675.     if (midnight_shutdown || !the_hint || !the_hint->widget.parent)
  676.     return;
  677.     
  678.     if (message_visible || (xterm_flag && xterm_hintbar)) {
  679.         set_hintbar(str);
  680.     }
  681. }
  682.  
  683. void rotate_dash (void)
  684. {
  685. #ifndef HAVE_X
  686.     static char rotating_dash [] = "|/-\\";
  687.     static int pos = 0;
  688.  
  689.     if (!nice_rotating_dash || (ok_to_refresh <= 0))
  690.     return;
  691.  
  692.     if (pos >= sizeof (rotating_dash)-1)
  693.     pos = 0;
  694.     move (0, COLS-1);
  695.     addch (rotating_dash [pos]);
  696.     refresh ();
  697.     pos++;
  698. #endif
  699. }
  700.  
  701. void remove_dash (void)
  702. {
  703. #ifndef HAVE_X
  704.     if (!nice_rotating_dash)
  705.     return;
  706.  
  707.     /* Currently, it's much nicer with the CPU to do this instead of
  708.        calling do_refresh.
  709.  
  710.        I should implement a routine called invalidate_region that would
  711.        send a draw message only to the affected views.  But for now
  712.        this is fine.
  713.     */
  714.     
  715.     move (0, COLS-1);
  716.     addch (' ');
  717. #endif    
  718. }
  719.  
  720. char *get_nth_panel_name (int num)
  721. {
  722.     static char buffer [20];
  723.     
  724.     if (!num)
  725.         return "New Left Panel";
  726.     else if (num == 1)
  727.         return "New Right Panel";
  728.     else {
  729.         sprintf (buffer, "%ith Panel", num);
  730.         return buffer;
  731.     }
  732. }
  733.  
  734. /* I wonder if I should start to use the folding mode than Dugan uses */
  735. /*                                                                     */
  736. /* This is the centralized managing of the panel display types         */
  737. /* This routine takes care of destroying and creating new widgets      */
  738. /* Please note that it could manage MAX_VIEWS, not just left and right */
  739. /* Currently nothing in the code takes advantage of this and has hard- */
  740. /* coded values for two panels only                                    */
  741.  
  742. /* Set the num-th panel to the view type: type */
  743. /* This routine also keeps at least one WPanel object in the screen */
  744. /* since a lot of routines depend on the current_panel variable */
  745. void set_display_type (int num, int type)
  746. {
  747.     int x, y, cols, lines;
  748.     int    the_other;        /* Index to the other panel */
  749.     char   *file_name = 0;    /* For Quick view */
  750.     Widget *new_widget, *old_widget;
  751.     WPanel  *the_other_panel;
  752.  
  753.     x =y = cols = lines = 0;
  754.     old_widget = 0;
  755.     if (num >= MAX_VIEWS){
  756.     fprintf (stderr, "Could not allocate more that %d views\n", MAX_VIEWS);
  757.     abort ();
  758.     }
  759.  
  760.     /* Check that we will have a WPanel * at least */
  761.     the_other = 0;
  762.     if (type != view_listing){
  763.     the_other = num == 0 ? 1 : 0;
  764.  
  765.     if (panels [the_other].type != view_listing)
  766.         return;
  767.  
  768.     }
  769.     
  770.     /* Get rid of it */
  771.     if (panels [num].widget){
  772.     Widget *w = panels [num].widget;
  773.     WPanel *panel = (WPanel *) panels [num].widget;
  774.     
  775.     x = w->x;
  776.     y = w->y;
  777.     cols  = w->cols;
  778.     lines = w->lines;
  779.     old_widget = panels [num].widget;
  780.  
  781.     if (panels [num].type == view_listing){
  782.         if (panel->frame_size == frame_full && type != view_listing){
  783.         cols = COLS - first_panel_size;
  784.         if (num == 1)
  785.             x = first_panel_size;
  786.         }
  787.     }
  788. #ifdef HAVE_TK
  789.     tk_evalf ("container_clean %s", panel->widget.wcontainer);
  790. #endif
  791.     }
  792.  
  793.     new_widget = 0;
  794.     
  795.     switch (type){
  796.     case view_listing:
  797.     new_widget = (Widget *) panel_new (get_nth_panel_name (num));
  798.     break;
  799.     
  800.     case view_info:
  801.     new_widget = (Widget *) info_new ();
  802.     
  803.     break;
  804.  
  805.     case view_tree:
  806.     new_widget = (Widget *) tree_new (1, 0, 0, 0, 0);
  807.     break;
  808.  
  809.     case view_quick:
  810.     new_widget = (Widget *) view_new (0, 0, 0, 0, 1);
  811.     the_other_panel = (WPanel *) panels [the_other].widget;
  812.     if (the_other_panel)
  813.         file_name =
  814.         the_other_panel->dir.list[the_other_panel->selected].fname;
  815.     else
  816.         file_name = "";
  817.     
  818.     view_init ((WView *) new_widget, 0, file_name);
  819.     break;
  820.     }
  821.     panels [num].type = type;
  822.     panels [num].widget = (Widget *) new_widget;
  823.     
  824.     /* We set the same size the old widget had */
  825.     widget_set_size ((Widget *) new_widget, y, x, lines, cols);
  826.     
  827.     /* We wanna the new widget at the same position */
  828.     /* XView sets wcontainer to !0 <- Not XView, but we, when we create it */
  829.     /* Ok, the XView support code does it */
  830.     if (old_widget && old_widget->wcontainer){
  831.     new_widget->wcontainer = old_widget->wcontainer;
  832.     new_widget->area = old_widget->area;
  833.     }
  834.  
  835.     /* We use replace to keep the circular list of the dialog in the */
  836.     /* same state.  Maybe we could just kill it and then replace it  */
  837.     if (midnight_dlg && old_widget){
  838.     dlg_replace_widget (midnight_dlg, old_widget, panels [num].widget);
  839.     }
  840.     if (type == view_listing){
  841.     if (num == 0)
  842.         left_panel = (WPanel *) new_widget;
  843.     else
  844.         right_panel = (WPanel *) new_widget;
  845.     }
  846.  
  847.     if (type == view_tree)
  848.     the_tree = (WTree *) new_widget;
  849. }
  850.  
  851. #ifndef HAVE_XVIEW
  852. /* This routine is deeply sticked to the two panels idea.
  853.    What should it do in more panels. ANSWER - don't use it
  854.    in any multiple panels environment. */
  855. void swap_panels ()
  856. {
  857.     Widget tmp;
  858.     Widget *tmp_widget;
  859.     WPanel panel;
  860.     WPanel *panel1, *panel2;
  861.     int tmp_type;
  862.     
  863. #if 0
  864. #ifdef HAVE_PORTABLE_TOKEN_PASTING
  865. #define panelswap(e) panel.##e = panel1->##e; panel1->##e = panel2->##e; panel2->##e = panel.##e;
  866. #define panelswapstr(e) strcpy (panel.##e, panel1->##e); strcpy (panel1->##e, panel2->##e); strcpy (panel2->##e, panel.##e);
  867. #else
  868. #define panelswap(e) panel./**/e = panel1->/**/e; panel1->/**/e = panel2->/**/e; panel2->/**/e = panel./**/e;
  869. #define panelswapstr(e) strcpy (panel./**/e, panel1->/**/e); strcpy (panel1->/**/e, panel2->/**/e); strcpy (panel2->/**/e, panel./**/e);
  870. #endif
  871. #endif
  872.  
  873. #define panelswap(x) panel. x = panel1-> x; panel1-> x = panel2-> x; panel2-> x = panel. x;
  874.  
  875. #define panelswapstr(e) strcpy (panel. e, panel1-> e); \
  876.                         strcpy (panel1-> e, panel2-> e); \
  877.                         strcpy (panel2-> e, panel. e);
  878.     panel1 = (WPanel *) panels [0].widget;
  879.     panel2 = (WPanel *) panels [1].widget;
  880.     if (panels [0].type == view_listing && panels [1].type == view_listing) {
  881.         /* Change everything except format/sort/panel_name etc. */
  882.         panelswap (dir);
  883.         panelswap (active);
  884.         panelswapstr (cwd);
  885.         panelswapstr (lwd);
  886.         panelswap (count);
  887.         panelswap (marked);
  888.         panelswap (dirs_marked);
  889.         panelswap (total);
  890.         panelswap (top_file);
  891.         panelswap (selected);
  892.         panelswap (is_panelized);
  893.         panelswap (dir_stat);
  894.     
  895.         panel1->searching = 0;
  896.         panel2->searching = 0;
  897.         if (current_panel == panel1)
  898.             current_panel = panel2;
  899.         else
  900.             current_panel = panel1;
  901.         if (midnight_dlg->current->widget == panels [0].widget)
  902.             dlg_select_widget (midnight_dlg, (void *) panels [1].widget);
  903.         else if (midnight_dlg->current->widget == panels [1].widget)
  904.             dlg_select_widget (midnight_dlg, (void *) panels [0].widget);
  905.     } else {
  906.     WPanel *tmp_panel;
  907.     
  908.     tmp_panel=right_panel;
  909.     right_panel=left_panel;
  910.     left_panel=tmp_panel;
  911.     
  912.     if (panels [0].type == view_listing) {
  913.             if (!strcmp (panel1->panel_name, get_nth_panel_name (0))) {
  914.                 free (panel1->panel_name);
  915.                 panel1->panel_name = strdup (get_nth_panel_name (1));
  916.             }
  917.         }
  918.         if (panels [1].type == view_listing) {
  919.             if (!strcmp (panel2->panel_name, get_nth_panel_name (1))) {
  920.                 free (panel2->panel_name);
  921.                 panel2->panel_name = strdup (get_nth_panel_name (0));
  922.             }
  923.         }
  924.         
  925.         tmp.x = panels [0].widget->x;
  926.         tmp.y = panels [0].widget->y;
  927.         tmp.cols = panels [0].widget->cols;
  928.         tmp.lines = panels [0].widget->lines;
  929.  
  930.         panels [0].widget->x = panels [1].widget->x;
  931.         panels [0].widget->y = panels [1].widget->y;
  932.         panels [0].widget->cols = panels [1].widget->cols;
  933.         panels [0].widget->lines = panels [1].widget->lines;
  934.  
  935.         panels [1].widget->x = tmp.x;
  936.         panels [1].widget->y = tmp.y;
  937.         panels [1].widget->cols = tmp.cols;
  938.         panels [1].widget->lines = tmp.lines;
  939.         
  940.         tmp_widget = panels [0].widget;
  941.         panels [0].widget = panels [1].widget;
  942.         panels [1].widget = tmp_widget;
  943.         tmp_type = panels [0].type;
  944.         panels [0].type = panels [1].type;
  945.         panels [1].type = tmp_type;
  946.     }
  947. }
  948. #endif
  949.  
  950. int get_display_type (int index)
  951. {
  952.     return panels [index].type;
  953. }
  954.  
  955. Widget *get_panel_widget (int index)
  956. {
  957.     return panels [index].widget;
  958. }
  959.  
  960. int get_current_index (void)
  961. {
  962.     if (panels [0].widget == ((Widget *) cpanel))
  963.     return 0;
  964.     else
  965.     return 1;
  966. }
  967.  
  968. int get_other_index (void)
  969. {
  970.     return !get_current_index ();
  971. }
  972.  
  973. /* Returns the view type for the current panel/view */
  974. int get_current_type (void)
  975. {
  976.     if (panels [0].widget == (Widget *) cpanel)
  977.     return panels [0].type;
  978.     else
  979.     return panels [1].type;
  980. }
  981.  
  982. /* Returns the view type of the unselected panel */
  983. int get_other_type (void)
  984. {
  985.     if (panels [0].widget == (Widget *) cpanel)
  986.     return panels [1].type;
  987.     else
  988.     return panels [0].type;
  989. }
  990.  
  991.